import Adapter from "./adapter";
import {Field, fieldKey} from "./field";


/*
  @Resource({ context: DbPool })
  @OAuth(['admin'])
  class User {

    @Field()
    @validator({ max: 10, min: 5 })
    firstName: string

    @Field()
    @validator({ regex: /\s{5,10}/ })
    lastName: string
  }
 */
export class Resource { // entity

  name: string;
  description?: string;
  fields: Field[];
  plugins: Plugin[];
  adapter: Adapter;

  constructor(config: ResourceConfigInternal) {
    this.name = config.name;
    this.description = config.description;
    this.fields = config.fields;
    this.adapter = config.adapter;

    this.init()
  }

  init() {
    this.adapter.register && this.adapter.register(this);
  }

  toConfig() {
    return {
      name: this.name,
      description: this.description,
      fields: this.fields.map(field => field.toConfig()),
      // plugins: this.plugins.map(plugin => plugin.toConfig()),
    }
  }

  group(queries: object) {
    if (!this.adapter.group) {
      throw new Error('This function is not implemented')
    }
    return this.adapter.group(this.name, queries);
  }

  find(queries: object): Promise<any[]> {
    if (!this.adapter.find) {
      throw new Error('This function is not implemented')
    }
    return this.adapter.find(this.name, queries);
  }

  findById(queries: object) {
    if (!this.adapter.findById) {
      throw new Error('This function is not implemented')
    }
    return this.adapter.findById(this.name, queries);
  }

  save(queries: object) {
    if (!this.adapter.save) {
      throw new Error('This function is not implemented')
    }
    return this.adapter.save(this.name, queries);
  }

  delete(queries: object) {
    if (!this.adapter.delete) {
      throw new Error('This function is not implemented')
    }
    return this.adapter.delete(this.name, queries);
  }

}


interface ResourceConfigInternal {
  name: string;
  description?: string;
  fields: Field[];
  adapter: Adapter;
}

export interface ResourceConfig {
  name?: string;
  description?: string;
  fields?: Field[];
  adapter: Adapter;
}


export const resourceKey = '__RESOURCE_KEY__';

export function resource(resourceConfig: ResourceConfig): ClassDecorator {
  return function (target) {
    const self = new Resource({
      ...resourceConfig,
      name: resourceConfig.name || target.name,
      fields: Reflect.getMetadata(fieldKey, target),
    });
    Reflect.defineMetadata(resourceKey, self, target);
  }
}

